package com.yunxi.module.system.service.tenant.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.yunxi.framework.common.enums.CommonStatusEnum;
import com.yunxi.framework.common.exception.util.ServiceExceptionUtil;
import com.yunxi.framework.common.pojo.PageResult;
import com.yunxi.framework.common.util.object.BeanUtils;
import com.yunxi.module.system.enums.constant.ErrorCodeConstants;
import com.yunxi.module.system.mapper.tenant.TenantPackageMapper;
import com.yunxi.module.system.model.tenant.TenantDO;
import com.yunxi.module.system.model.tenant.TenantPackageDO;
import com.yunxi.module.system.service.tenant.TenantPackageService;
import com.yunxi.module.system.service.tenant.TenantService;
import com.yunxi.module.system.vo.admin.tenant.packages.TenantPackagePageReqVO;
import com.yunxi.module.system.vo.admin.tenant.packages.TenantPackageSaveReqVO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 租户套餐 Service 接口实现类
 * </p>
 *
 * @author lidy
 * @since 2024-05-08
 */
@Service
@Validated
public class TenantPackageServiceImpl implements TenantPackageService {

    @Resource
    private TenantPackageMapper tenantPackageMapper;

    @Resource
    @Lazy // 避免循环依赖的报错
    private TenantService tenantService;

    /**
     * 获得租户套餐
     *
     * @param packageId 套餐编号
     * @return 套餐信息
     */
    @Override
    public TenantPackageDO getTenantPackage(Long packageId) {
        return tenantPackageMapper.selectById(packageId);
    }

    /**
     * 校验租户套餐
     *
     * @param packageId 租户套餐编号
     * @return 租户套餐信息
     */
    @Override
    public TenantPackageDO validateTenantPackage(Long packageId) {
        // 根据租户套餐编号查询
        TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(packageId);
        if (tenantPackageDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS);
        }
        if (!tenantPackageDO.getStatus().equals(CommonStatusEnum.ENABLE.getStatus())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENANT_PACKAGE_DISABLE, tenantPackageDO.getName());
        }
        return tenantPackageDO;
    }

    /**
     * 获得租户套餐分页列表
     *
     * @param reqVO 条件
     * @return 租户套餐分页列表
     */
    @Override
    public PageResult<TenantPackageDO> getTenantPackagePage(TenantPackagePageReqVO reqVO) {
        return tenantPackageMapper.selectPage(reqVO);
    }

    /**
     * 创建租户套餐
     *
     * @param createReqVO 租户套餐信息
     * @return 套餐编号
     */
    @Override
    public Long createTenantPackage(TenantPackageSaveReqVO createReqVO) {
        // 创建
        TenantPackageDO tenantPackageDO = BeanUtils.toBean(createReqVO, TenantPackageDO.class);
        tenantPackageMapper.insert(tenantPackageDO);
        // 返回
        return tenantPackageDO.getId();
    }

    /**
     * 更新租户套餐
     * 多数据源，使用 @DSTransactional 保证本地事务，以及数据源的切换
     *
     * @param updateReqVO 租户套餐信息
     */
    @Override
    @DSTransactional
    public void updateTenantPackage(TenantPackageSaveReqVO updateReqVO) {
        // 校验
        TenantPackageDO tenantPackageDO = validateTenantPackageExists(updateReqVO.getId());

        // 更新
        TenantPackageDO updateObj = BeanUtils.toBean(updateReqVO, tenantPackageDO.getClass());
        tenantPackageMapper.updateById(updateObj);
        // 如果租户发生变化,修改每个租户的菜单
        if (!CollUtil.isEqualList(tenantPackageDO.getMenuIds(), updateObj.getMenuIds())) {
            List<TenantDO> tenantDOS = tenantService.getTenantListByPackageId(tenantPackageDO.getId());
            tenantDOS.forEach(tenantDO -> tenantService.updateTenantRoleMenu(tenantDO.getId(), updateObj.getMenuIds()));
        }
    }

    /**
     * 删除租户套餐
     *
     * @param tenantId 租户套餐编号
     */
    @Override
    public void deleteTenantPackage(Long tenantId) {
        // 校验是否存在
        validateTenantPackageExists(tenantId);

        // 校验正在使用
        validateTenantUsed(tenantId);

        // 删除
        tenantPackageMapper.deleteById(tenantId);
    }


    /**
     * 获得租户套餐精简信息列表
     *
     * @param status 状态
     * @return 租户套餐精简信息列表
     */
    @Override
    public List<TenantPackageDO> getTenantPackageListByStatus(Integer status) {
        return tenantPackageMapper.selectListByStatus(status);
    }

    /**
     * 校验套餐是否正在使用
     *
     * @param tenantId 租户套餐编号
     */
    private void validateTenantUsed(Long tenantId) {
        if (tenantService.getTenantCountByPackageId(tenantId) > 0) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENANT_PACKAGE_USED);
        }
    }

    /**
     * 校验租户套餐是否存在
     *
     * @param tenantId 租户套餐编号
     * @return 租户套餐信息
     */
    private TenantPackageDO validateTenantPackageExists(Long tenantId) {
        TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantId);
        if (tenantPackageDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS);
        }
        return tenantPackageDO;
    }
}
